#!/usr/bin/python

import sys
from socket import *
#import cjson
import simplejson as json
#from cPickle import *
from time import *

teamName = "max"
teamKey  = "note70mann"
server   = "114.80.213.55"
port     = 12345
#1024 worked fine for both test and competition rounds
buffer   = 1024

#switch to simplejson functions, but be warned they might be too slow.
#decode=cjson.decode
#encode=cjson.encode
decode=json.loads
encode=json.dumps

def evaluateS(price,quantitysold,quantityown,quantitymarket,prod):
    #put your evaluation function here, currently buys everything offered
    #if prod in averagePrice.keys() and averagePrice[prod] * 9 < price:
    #    buyflag = False
    #    bidprice = price
    #    bidquantity = quantitysold
    #el
    if (cash + portfoliovalue * 0.9) > 250000:
        buyflag = False
        bidprice = price
        bidquantity = quantitysold
        try:
            qtmp = int(100000/bidprice)
            if qtmp < quantitysold:
                bidquantity = qtmp
            else:
                bidquantity = quantitysold
        except:
            bidquantity = quantitysold
    elif (totalRounds - currentRound) < 10:
        buyflag=True
        bidprice=price
        bidquantity=quantitysold
        try:
            qtmp = int(100000/bidprice)
            if qtmp < quantitysold:
                bidquantity = qtmp
            else:
                bidquantity = quantitysold
        except:
            bidquantity = quantitysold
    elif price * quantitysold > (marketCash - cash):
        buyflag=True
        bidprice=price
        bidquantity=quantitysold
        try:
            qtmp = int(100000/bidprice)
            if qtmp < quantitysold:
                bidquantity = qtmp
            else:
                bidquantity = quantitysold
        except:
            bidquantity = quantitysold
    else:
        buyflag = True
        bidprice = price * 1.05
        bidquantity = quantitysold
        try:
            qtmp = int(100000/bidprice)
            if qtmp < quantitysold:
                bidquantity = qtmp
            else:
                bidquantity = quantitysold
        except:
            bidquantity = quantitysold
    return buyflag,bidprice,bidquantity

def evaluateD(price,quantityasked,quantityown,quantitymarket,prod):
    #put your evaluation function here, currently sells everything asked
    if (cash + portfoliovalue * 0.9) > 250000:
        sellflag = True
        bidprice = price
        bidquantity = quantityasked
        try:
            qtmp = int(100000/bidprice)
            if qtmp < quantityasked:
                bidquantity = qtmp
            else:
                bidquantity = quantityasked
        except:
            bidquantity = quantityasked
    elif quantityown == 0:
        sellflag = False
        bidprice = price
        bidquantity = quantityasked
        try:
            qtmp = int(100000/bidprice)
            if qtmp < quantityasked:
                bidquantity = qtmp
            else:
                bidquantity = quantityasked
        except:
            bidquantity = quantityasked
    elif (totalRounds - currentRound) < 20 and averagePrice[prod] < price * 0.9:
        sellflag=True
        bidprice=price*0.93
        bidquantity=quantityasked
        try:
            qtmp = int(100000/bidprice)
            if qtmp < quantityasked:
                bidquantity = qtmp
            else:
                bidquantity = quantityasked
        except:
            bidquantity = quantityasked
    elif averagePrice[prod] > price * 1.2:
        sellflag = False
        bidprice = price
        bidquantity = quantityasked
        try:
            qtmp = int(100000/bidprice)
            if qtmp < quantityasked:
                bidquantity = qtmp
            else:
                bidquantity = quantityasked
        except:
            bidquantity = quantityasked
    elif prod in marketportfolio.keys() and (marketportfolio[prod] - quantityown) < quantityasked:
        sellflag=True
        bidprice=price
        bidquantity=quantityasked
        try:
            qtmp = int(100000/bidprice)
            if qtmp < quantityasked:
                bidquantity = qtmp
            else:
                bidquantity = quantityasked
        except:
            bidquantity = quantityasked
    else:
        sellflag=True
        bidprice=price*0.95
        bidquantity=quantityasked
        try:
            qtmp = int(100000/bidprice)
            if qtmp < quantityasked:
                bidquantity = qtmp
            else:
                bidquantity = quantityasked
        except:
            bidquantity = quantityasked
    return sellflag,bidprice,bidquantity

portfolio={}
averagePrice = {}
marketportfolio={}
cash=0
currentRound=0
marketCash = 0
marketInventory = {}
inventoryAveragePrice = {}

def getOrder(roundStart):
    "Calculate your order here and return it as a dict"
    bids = []
    newbid = {"side":"BUY", "teamName":teamName}
    for i,bid in enumerate(roundStart["supply"]):
        prod=bid["productId"]
        price=bid["price"]
        try:
            quantown=portfolio[prod]
        except KeyError:
            quantown=0
        try:
            quantmarket=marketportfolio[prod]
        except KeyError:
            quantmarket=0
        quantbid=bid["quantity"]
        buyflag,mybidprice,mybidquantity=evaluateS(price,quantbid,quantown,quantmarket,prod)
        if(buyflag):
            mybid = newbid.copy()
            mybid["orderId"] = "buybid"+str(i)
            mybid["productId"] = prod
            mybid["price"] = mybidprice
            mybid["quantity"] = int(mybidquantity)
            bids.append(mybid)
    # Append a created bid to your list
    

    # Do likewise for your asks
    asks=[]
    newask = {"side":"SELL", "teamName":teamName}
    for i,bid in enumerate(roundStart["demand"]):
        prod=bid["productId"]
        price=bid["price"]
        try:
            quantown=portfolio[prod]
        except KeyError:
            continue
        try:
            quantmarket=marketportfolio[prod]
        except KeyError:
            quantmarket=0
        quantreq=bid["quantity"]
        sellflag,mybidprice,mybidquantity=evaluateD(price,quantbid,quantown,quantmarket,prod)
        if(sellflag):
            myask = newask.copy()
            myask["orderId"] = "sellbid"+str(i)
            myask["productId"] = prod
            myask["price"] = mybidprice
            myask["quantity"] = int(mybidquantity)
            asks.append(myask)
    order = {"Order": {"bids": bids, "asks": asks}}
    return order

def processRoundStart(roundStart):
    for item in roundStart['portfolio']['positions']:
        portfolio[item["productId"]]=item["quantity"]
    #process the RoundStart
    
def processRoundEnd(roundEnd):
    "Do any processing you want with the round end data here"
    for item in roundEnd["marketTransactions"]:
        try:
            marketportfolio[item["productId"]]=marketportfolio[item["productId"]]+item["quantity"]
        except KeyError:
            marketportfolio[item["productId"]]=item["quantity"]

def getRoundVariables(roundStart):
    dem = roundStart["demand"]
    sup = roundStart["supply"]
    log.write("[demand]"+ str(dem) + "\n")
    log.write("[supply]"+ str(sup) + "\n")
    portf = roundStart["portfolio"]

def getMarketVariables(roundEnd):
    marketTrans = roundEnd["marketTransactions"]
    winAsks = roundEnd["winningAsks"]
    for item in winAsks:
        prod = item["productId"]
        p = item["price"]
        q = item["quantity"]
        if prod in averagePrice.keys():
            averagePrice[prod] = (portfolio[prod] * averagePrice[prod] + q * p)/(portfolio[prod] + q)
        else:
            averagePrice[prod] = p
        
    winBids = roundEnd["winningBids"]
    for item in winBids:
        prod = item["productId"]
        p = item["price"]
        q = item["quantity"]
        if prod in averagePrice.keys():
            averagePrice[prod] = (portfolio[prod] * averagePrice[prod] + q * p)/(portfolio[prod] + q)
        else:
            averagePrice[prod] = p

    log.write("[winningAsks]"+ str(winAsks) + "\n")
    log.write("[winningBids]"+ str(winBids) + "\n")
    roundMarketCash = 0
    roundMarketInventory = {}
    for item in marketTrans:
        price = item["price"]
        productId = item["productId"]
        quantity = item["quantity"]
        roundMarketCash += price * quantity
        if productId in roundMarketInventory.keys():
            roundMarketInventory[productId] += quantity
        else:
            roundMarketInventory[productId] = quantity
    return roundMarketCash, roundMarketInventory

def mergeDict(d1, d2):
    res = d1
    for k in d2:
        if k in res.keys():
            res[k] += d2[k]
        else:
            res[k] = d2[k]
    return res

#MAIN LOOP
log = open('info_log', 'w+')
err = open('error_log', 'w+')
s = socket(AF_INET, SOCK_STREAM)
s.connect((server, port))
f=s.makefile('r',0)
login=encode({"Login":{"teamName":teamName,"key":teamKey}})
s.send(login+"\n")

# Get the Welcome Message back
welcome = decode(f.readline())['Welcome']
print welcome
totalRounds = welcome["roundTotal"]
cash = welcome["initialCash"]
portfoliovalue=0
currentRound = 0

while currentRound<totalRounds:
    print currentRound,cash,portfoliovalue,str(cash + portfoliovalue * 0.9)
    # Get the Round Start Message
    js=f.readline()
    timestart=time()
    try:
        roundStart = decode(js)["RoundStart"]
    except KeyError:
        err.write("Decoding problem with " + js)
        print "Decoding problem with ",js

    processRoundStart(roundStart)
    
    cash = roundStart["portfolio"]["cashValue"]
    portfoliovalue=roundStart['portfolio']['inventoryValue']
    currentRound = roundStart["roundNumber"]

    # Process the info, come up with our order,
    # send it off, and get back the Ack

    getRoundVariables(roundStart)
    
    myOrder = getOrder(roundStart)
    s.send(encode(myOrder)+"\n")
    js=f.readline()
    try:
        Ack=decode(js)["Ack"]
    except KeyError:
        err.write("Decoding problem with " + js)
        print "Decoding problem with ",js

    # Get the Round End, do Round End calculations
    js=f.readline()
    try:
        roundEnd=decode(js)["RoundEnd"]
    except KeyError:
        err.write("Decoding problem with " + js)
        print "Decoding problem with ",js

    roundMarketCash, roundMarketInventory = getMarketVariables(roundEnd)
    marketCash += roundMarketCash
    log.write("[roundMarketCash]     "+ str(roundMarketCash) + "\n")
    log.write("[marketCash]          "+ str(marketCash) + "\n")
    log.write("[roundMarketInventory]"+ str(roundMarketInventory) + "\n")
    log.write("[marketInventory]     "+ str(marketInventory) + "\n")
    marketInventory = mergeDict(marketInventory, roundMarketInventory)
    
    processRoundEnd(roundEnd)
    log.write("[averagePrice]" + str(averagePrice) + "\n")
    log.write("[portfolio]" + str(portfolio) + "\n")

# The Game is over, print out how we did
js=f.readline()
try:
    gameEnd=decode(js)["GameEnd"]
except KeyError:
    print "Decoding problem with ",js
    err.write("Decoding problem with " + js)
print ("marketCash: %d" % marketCash)
print "marketInventory: ", marketInventory
print "marketportfolio: ", marketportfolio

print ("cash: %f" % gameEnd["portfolio"]["cashValue"])
print ("inv : %f" % gameEnd["portfolio"]["inventoryValue"])
print ("tot : %f" % (gameEnd["portfolio"]["cashValue"] + gameEnd["portfolio"]["inventoryValue"] * 0.9))


